Gracefully handle duplicate package in a lockfile
authorAleksey Kladov <aleksey.kladov@gmail.com>
Tue, 9 Aug 2016 12:14:26 +0000 (15:14 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Tue, 9 Aug 2016 12:18:53 +0000 (15:18 +0300)
src/cargo/core/resolver/encode.rs
src/cargo/ops/lockfile.rs
tests/bad-config.rs

index 8771a95328bb4cc05a555f87c036b466fe88bbc9..ca4cdec2e5b99e42a111d59ed482ff1880cf7635 100644 (file)
@@ -20,7 +20,7 @@ pub struct EncodableResolve {
 pub type Metadata = BTreeMap<String, String>;
 
 impl EncodableResolve {
-    pub fn to_resolve(self, ws: &Workspace) -> CargoResult<Resolve> {
+    pub fn into_resolve(self, ws: &Workspace) -> CargoResult<Resolve> {
         let path_deps = build_path_deps(ws);
         let default = try!(ws.current()).package_id().source_id();
 
@@ -48,14 +48,17 @@ impl EncodableResolve {
             let mut register_pkg = |pkgid: &PackageId| {
                 let precise = pkgid.source_id().precise()
                                    .map(|s| s.to_string());
-                assert!(tmp.insert(pkgid.clone(), precise).is_none(),
-                        "a package was referenced twice in the lockfile");
+                if tmp.insert(pkgid.clone(), precise).is_some() {
+                    return Err(internal(format!("package `{}` is specified twice in the lockfile",
+                                                pkgid.name())));
+                }
                 g.add(pkgid.clone(), &[]);
+                Ok(())
             };
 
-            register_pkg(&root);
+            try!(register_pkg(&root));
             for id in ids.iter() {
-                register_pkg(id);
+                try!(register_pkg(id));
             }
         }
 
index 91a2bf2d7a051053c590e32e04366c4aeec89051..2afb4d534db9e71359524182e958527d70ab0c78 100644 (file)
@@ -26,7 +26,7 @@ pub fn load_pkg_lockfile(ws: &Workspace) -> CargoResult<Option<Resolve>> {
         let table = toml::Value::Table(table);
         let mut d = toml::Decoder::new(table);
         let v: resolver::EncodableResolve = try!(Decodable::decode(&mut d));
-        Ok(Some(try!(v.to_resolve(ws))))
+        Ok(Some(try!(v.into_resolve(ws))))
     }).chain_error(|| {
         human(format!("failed to parse lock file at: {}", f.path().display()))
     })
index 15324711fbbdf20abbe14f01f4227fb2379fa437..ef1912d4728973f09f19983ad3802acf905a7317 100644 (file)
@@ -236,6 +236,50 @@ Caused by:
 "));
 }
 
+#[test]
+fn duplicate_packages_in_cargo_lock() {
+    Package::new("foo", "0.1.0").publish();
+
+    let p = project("bar")
+        .file("Cargo.toml", r#"
+            [project]
+            name = "bar"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies]
+            foo = "0.1.0"
+        "#)
+        .file("src/lib.rs", "")
+        .file("Cargo.lock", r#"
+            [root]
+            name = "bar"
+            version = "0.0.1"
+            dependencies = [
+             "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            ]
+
+            [[package]]
+            name = "foo"
+            version = "0.1.0"
+            source = "registry+https://github.com/rust-lang/crates.io-index"
+
+            [[package]]
+            name = "foo"
+            version = "0.1.0"
+            source = "registry+https://github.com/rust-lang/crates.io-index"
+        "#);
+    p.build();
+
+    assert_that(p.cargo("build").arg("--verbose"),
+                execs().with_status(101).with_stderr("\
+[ERROR] failed to parse lock file at: [..]
+
+Caused by:
+  package `foo` is specified twice in the lockfile
+"));
+}
+
 #[test]
 fn bad_git_dependency() {
     let foo = project("foo")